package components

import (
	"web/actions"
	"web/api"
	"web/store"
	v "github.com/gopherjs/vecty"
	"github.com/gopherjs/vecty/elem"
	"github.com/gopherjs/vecty/event"
	"github.com/gopherjs/vecty/prop"
	"marwan.io/vecty-router"
	"marwan.io/vstore"
)


type NavBar struct {
	v.Core
	CurrentBranchName  string `vecty:"prop"`
	Username           string `vecty:"prop"`
	LoggedIn           bool   `vecty:"prop"`
	ActiveRoute        string `vecty:"prop"`
	SearchProjectsText string `vecty:"prop"`
}

func (n *NavBar) Connect(s vstore.Store) {
	state := s.State().(*store.State)
	n.Username = state.User.Name
	n.LoggedIn = state.User.LoggedIn
	n.ActiveRoute = state.NavBar.ActiveRoute
}

func (n *NavBar) onLoginClick(e *v.Event) {
	if n.LoggedIn {
		return
	}
	store.GetDialog().Dispatch(GetShowDialogAction(n.Username))
}

func GetShowDialogAction(username string) *actions.ShowDialog {
	return &actions.ShowDialog{
		Title: "登录（LDAP 认证）",
		Child: &LoginForm{
			Username: username,
		},
		OnOk: func(c actions.DialogChild) bool {
			l := c.(*LoginForm)
			loginInfo := l.GetValue()
			err := api.Login(loginInfo)
			if err != nil {
				println("failed to login", err.Error())
				setDialogErrMsg("认证失败: " + err.Error())
				return false
			}
			store.Get().Dispatch(&actions.LoginSuccess{
				Username: loginInfo.Username,
			})
			router.Redirect("/project")
			store.Get().Dispatch(&actions.SetActiveRoute{
				Route: "/project",
			})
			return true
		},
	}
}

func (n *NavBar) onLogoutClick(e *v.Event) {
	store.Get().Dispatch(&actions.Logout{})
	err := api.Logout()
	if err != nil {
		println("failed to logout:", err.Error())
	}
}

func (n *NavBar) renderNavItems(branchName string) v.List {
	routeTexts := []routeText{
		{"/branch", "分支 ( " + branchName + " )"},
		{"/repo", "仓库"},
		{"/project", "项目"},
		{"/topic", "主题"},
	}
	items := make(v.List, len(routeTexts))
	for idx, rt := range routeTexts {
		items[idx] = &NavItem{
			Route:  rt.route,
			Text:   rt.text,
			Active: rt.route == n.ActiveRoute,
		}
	}
	return items
}

type routeText struct {
	route string
	text  string
}

func (n *NavBar) Render() v.ComponentOrHTML {
	branchName := "未知"
	if n.CurrentBranchName != "" {
		branchName = n.CurrentBranchName
	}
	username := "登录"
	if n.Username != "" && n.LoggedIn {
		username = n.Username
	}

	return elem.Navigation(
		v.Markup(
			v.Class("navbar", "is-info"),
		),

		elem.Div(
			v.Markup(
				v.Class("navbar-brand"),
			),

			elem.Anchor(
				v.Markup(
					v.Class("navbar-item"),
					prop.Href("#"),
				),

				elem.Image(
					v.Markup(
						prop.Src("/icons/logo.svg"),
					),
				),
			),
		),

		elem.Div(
			v.Markup(
				v.Class("navbar-menu"),
			),

			elem.Div(
				v.Markup(
					v.Class("navbar-start"),
				),
				n.renderNavItems(branchName),
			),

			elem.Div(
				v.Markup(
					v.Class("navbar-end"),
					v.Style("align-items", "center"),
				),

				elem.Div(
					v.Markup(
						v.Class("navbar-item"),
					),

					elem.Anchor(
						v.Markup(
							v.Class("navbar__username", "has-text-white"),
							prop.Href("#"),
							event.Click(n.onLoginClick),
						),
						v.Text(username),
					),
					v.If(n.LoggedIn,
						elem.Button(
							v.Markup(
								v.Class("button", "is-info", "is-small"),
								event.Click(n.onLogoutClick),
							),
							v.Text("登出"),
						),
					),
				),
			),
		),
	)
}

type NavItem struct {
	v.Core
	Text   string `vecty:"prop"`
	Active bool   `vecty:"prop"`
	Route  string `vecty:"prop"`
}

func (ni *NavItem) Render() v.ComponentOrHTML {
	return elem.Anchor(
		v.Markup(
			v.ClassMap{"navbar-item": true, "is-active": ni.Active},
			prop.Href(ni.Route),
			event.Click(func(e *v.Event) {
				store.Get().Dispatch(&actions.SetActiveRoute{
					Route: ni.Route,
				})
				router.Redirect(ni.Route)
			}).PreventDefault(),
		),
		v.Text(ni.Text),
	)
}
